//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace Microsoft.Research.ScientificWorkflow.UIDesigner.Monitor
{
    using System;
    using System.Collections.ObjectModel;
    using System.Globalization;
    using Microsoft.Research.ScientificWorkflow.TridentModel;
    using Microsoft.Research.ScientificWorkflow.UIDesigner.Commands;
    using Microsoft.Research.ScientificWorkflow.UIDesigner.WpfComposite;
    using Microsoft.Practices.Unity;
    using Microsoft.Research.eResearch.Subscriber.Interfaces;
    using WorkflowApplication.Interfaces;
    using System.Windows.Controls;
    using System.ComponentModel;
    using Microsoft.Research.DataLayer;
    using Microsoft.Research.eResearch.Common.Linq;
    using Microsoft.Research.ScientificWorkflow.TridentUtilities;
    using TridentAPI;
    using Microsoft.Research.ScientificWorkflow.TridentComposer;

    /// <summary>
    /// This is a presenter for the workflow outputs in the workflow app.
    /// </summary>
    public partial class WorkflowParametersPresentationModel : ICenterPanePresenter
    {
        /// <summary>
        /// Gets or sets the data product presentation controller.
        /// </summary>
        /// <value>The data product presentation controller.</value>
        public DataProductPresentationModel DataProductPresentationController { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="WorkflowParametersPresentationModel"/> class.
        /// </summary>
        /// <param name="container">The container.</param>
        /// <param name="view">The view.</param>
        public WorkflowParametersPresentationModel(IUnityContainer container, WorkflowParametersView view, DataProductPresentationModel dataProductModel)
        {
            this.View = view;
            this.WorkflowOutputCollection = new ObservableCollection<WorkflowOutputProperty>();
            this.WorkflowInputPropertyCollection = new ObservableCollection<WorkflowRequiredInputProperty>();
            this.Container = container;
            this.View.Model = this;
            this.DataProductPresentationController = dataProductModel;
            this.ShowDataProducts = true;
            this.View.brdrDataProducts.Child = dataProductModel.View;
        }

        /// <summary>
        /// Refreshes the outputs.
        /// </summary>
        /// <param name="job">The job.</param>
        public void RefreshOutputs(Job job)
        {
            try
            {
                if (job != null && job.ActivityInstances.Count > 0 && job.ActivityInstances[0].Outputs.Count > 0)
                {
                    job.ActivityInstances[0].Outputs
                        .ForEach(item => this.LookupOrCreate(this.WorkflowOutputCollection
                            ,DataProductService.GenerateDataProductItem(item)));
                }
            }
            catch (Exception)
            {
                //No need to notify the user as the operation will automatically be flagged as aborted and indicated to the user directly.
            }
        }

        /// <summary>
        /// Retrieves the data product item.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <returns></returns>
        public DataProductItem RetrieveDataProduct(IObject item)
        {
            return this.Container.Resolve<IDataProductService>().GenerateDataProductItem((item as IObject).ID);
        }

        /// <summary>
        /// Assigns the selection.
        /// </summary>
        private void AssignSelection()
        {
            this.ClearContent();
            this.CurrentWorkflowModel.GetWorkflowRequiredParameters().ForEach(item => this.AssignInputValue(item));
        }

        /// <summary>
        /// Assign the input value.
        /// </summary>
        /// <param name="paramModel">
        /// The parameter description model.
        /// </param>
        private void AssignInputValue(ParameterDescriptionModel paramModel)
        {
            if (paramModel != null)
            {
                string displayVal = string.Empty;
                if (paramModel.Value != null)
                {
                    displayVal = paramModel.Value.ToString();
                }

                try
                {
                    TypeInitializer typeInit = TypeProviderHelper.FetchTypeInitializer(paramModel.DataType, Runtime.WPF);
                    if (typeInit != null)
                    {
                        string deserializedVal = (paramModel.Value != null) ? paramModel.Value.ToString() : string.Empty;
                        BaseTypeInitializer baseTypeinit = ActivityComposer.LoadInitializer(typeInit, deserializedVal);
                        if (baseTypeinit != null)
                        {
                            displayVal = baseTypeinit.GetStringValue();
                        }
                    }
                }
                catch (Exception)
                {
                    // Do not do anything, if typeinitializer is not available, the string converted value will be shown.
                }

                string activityName = paramModel.PropertyPaneDisplayName.Split(".".ToCharArray())[0];
                this.WorkflowInputPropertyCollection.Add(
                    new WorkflowRequiredInputProperty() { DisplayName = paramModel.PropertyPaneDisplayName, Value = displayVal, ActivityUniqueName = activityName, PropertyName = paramModel.Name });
            }
        }

        /// <summary>
        /// Clears the content.
        /// </summary>
        private void ClearContent()
        {
            this.WorkflowInputPropertyCollection.Clear();
            this.WorkflowOutputCollection.Clear();
            this.DataProductPresentationController.DataProductsViewCollection.Clear();
        }

        #region ICenterPanePresenter Members

        /// <summary>
        /// Gets or sets the content view.
        /// </summary>
        /// <value>The content view.</value>
        public UserControl ContentView
        {
            get
            {
                return (UserControl)this.View;
            }

            set
            {
                WorkflowParametersView view = value as WorkflowParametersView;
                if (view != null)
                {
                    this.View = view;
                }
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is initialized.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is initialized; otherwise, <c>false</c>.
        /// </value>
        public bool IsInitialized { get; set; }

        /// <summary>
        /// Gets or sets the current workflow model.
        /// </summary>
        /// <value>The current workflow model.</value>
        public TridentWorkflowModel CurrentWorkflowModel
        {
            get
            {
                return this.currentWorkflowModel;
            }
            set
            {
                this.currentWorkflowModel = value;
                this.AssignSelection();
                this.RaisePropertyChanged("CurrentWorkflowModel");
            }
        }

        #endregion
    }
}
